home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / TEXTURE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  68.1 KB  |  2,291 lines

  1. /* $Id: texture.c,v 3.8 1998/06/11 02:04:41 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: texture.c,v $
  26.  * Revision 3.8  1998/06/11 02:04:41  brianp
  27.  * fixed texture clamp problem when coord==1 (bad sampling)
  28.  *
  29.  * Revision 3.7  1998/03/28 03:58:16  brianp
  30.  * added CONST macro to fix IRIX compilation problems
  31.  *
  32.  * Revision 3.6  1998/03/27 04:26:44  brianp
  33.  * fixed G++ warnings
  34.  *
  35.  * Revision 3.5  1998/03/15 18:12:37  brianp
  36.  * fixed sampling bug when filter=NEAREST and wrap=CLAMP
  37.  *
  38.  * Revision 3.4  1998/03/01 20:19:26  brianp
  39.  * fixed a few sampling functions to prevent access of missing mipmap levels
  40.  *
  41.  * Revision 3.3  1998/02/20 04:53:37  brianp
  42.  * implemented GL_SGIS_multitexture
  43.  *
  44.  * Revision 3.2  1998/02/03 04:27:54  brianp
  45.  * added texture lod clamping
  46.  *
  47.  * Revision 3.1  1998/02/01 19:39:09  brianp
  48.  * added GL_CLAMP_TO_EDGE texture wrap mode
  49.  *
  50.  * Revision 3.0  1998/01/31 21:04:38  brianp
  51.  * initial rev
  52.  *
  53.  */
  54.  
  55.  
  56. #ifdef PC_HEADER
  57. #include "all.h"
  58. #else
  59. #include <math.h>
  60. #include <stdlib.h>
  61. #include "context.h"
  62. #include "macros.h"
  63. #include "mmath.h"
  64. #include "pb.h"
  65. #include "texture.h"
  66. #include "types.h"
  67. #endif
  68.  
  69.  
  70.  
  71. /*
  72.  * Perform automatic texture coordinate generation.
  73.  * Input:  ctx - the context
  74.  *         n - number of texture coordinates to generate
  75.  *         obj - array of vertexes in object coordinate system
  76.  *         eye - array of vertexes in eye coordinate system
  77.  *         normal - array of normal vectores in eye coordinate system
  78.  * Output:  texcoord - array of resuling texture coordinates
  79.  */
  80. void gl_texgen( GLcontext *ctx, GLint n,
  81.                 GLfloat obj[][4], GLfloat eye[][4],
  82.                 GLfloat normal[][3], GLfloat texcoord[][4],
  83.                 GLuint textureSet)
  84. {
  85.    struct gl_texture_set *texSet = &ctx->Texture.Set[textureSet];
  86.  
  87.    /* special case: S and T sphere mapping */
  88.    if (texSet->TexGenEnabled==(S_BIT|T_BIT)
  89.        && texSet->GenModeS==GL_SPHERE_MAP
  90.        && texSet->GenModeT==GL_SPHERE_MAP) {
  91.       GLint i;
  92.       for (i=0;i<n;i++) {
  93.          GLfloat u[3], two_nu, m, fx, fy, fz;
  94.          COPY_3V( u, eye[i] );
  95.          NORMALIZE_3FV( u );
  96.          two_nu = 2.0F * DOT3(normal[i],u);
  97.          fx = u[0] - normal[i][0] * two_nu;
  98.          fy = u[1] - normal[i][1] * two_nu;
  99.          fz = u[2] - normal[i][2] * two_nu;
  100.          m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0F)*(fz+1.0F) );
  101.          if (m==0.0F) {
  102.             texcoord[i][0] = 0.5F;
  103.             texcoord[i][1] = 0.5F;
  104.          }
  105.          else {
  106.             GLfloat mInv = 1.0F / m;
  107.             texcoord[i][0] = fx * mInv + 0.5F;
  108.             texcoord[i][1] = fy * mInv + 0.5F;
  109.          }
  110.       }
  111.       return;
  112.    }
  113.  
  114.    /* general solution */
  115.    if (texSet->TexGenEnabled & S_BIT) {
  116.       GLint i;
  117.       switch (texSet->GenModeS) {
  118.          case GL_OBJECT_LINEAR:
  119.             for (i=0;i<n;i++) {
  120.                texcoord[i][0] = DOT4( obj[i], texSet->ObjectPlaneS );
  121.             }
  122.             break;
  123.          case GL_EYE_LINEAR:
  124.             for (i=0;i<n;i++) {
  125.                texcoord[i][0] = DOT4( eye[i], texSet->EyePlaneS );
  126.             }
  127.             break;
  128.          case GL_SPHERE_MAP:
  129.             for (i=0;i<n;i++) {
  130.                GLfloat u[3], two_nu, m, fx, fy, fz;
  131.                COPY_3V( u, eye[i] );
  132.                NORMALIZE_3FV( u );
  133.                two_nu = 2.0*DOT3(normal[i],u);
  134.                fx = u[0] - normal[i][0] * two_nu;
  135.                fy = u[1] - normal[i][1] * two_nu;
  136.                fz = u[2] - normal[i][2] * two_nu;
  137.                m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  138.                if (m==0.0F) {
  139.                   texcoord[i][0] = 0.5F;
  140.                }
  141.                else {
  142.                   texcoord[i][0] = fx / m + 0.5F;
  143.                }
  144.             }
  145.             break;
  146.          default:
  147.             gl_problem(ctx, "Bad S texgen");
  148.             return;
  149.       }
  150.    }
  151.  
  152.    if (texSet->TexGenEnabled & T_BIT) {
  153.       GLint i;
  154.       switch (texSet->GenModeT) {
  155.          case GL_OBJECT_LINEAR:
  156.             for (i=0;i<n;i++) {
  157.                texcoord[i][1] = DOT4( obj[i], texSet->ObjectPlaneT );
  158.             }
  159.             break;
  160.          case GL_EYE_LINEAR:
  161.             for (i=0;i<n;i++) {
  162.                texcoord[i][1] = DOT4( eye[i], texSet->EyePlaneT );
  163.             }
  164.             break;
  165.          case GL_SPHERE_MAP:
  166.             for (i=0;i<n;i++) {
  167.                GLfloat u[3], two_nu, m, fx, fy, fz;
  168.                COPY_3V( u, eye[i] );
  169.                NORMALIZE_3FV( u );
  170.                two_nu = 2.0*DOT3(normal[i],u);
  171.                fx = u[0] - normal[i][0] * two_nu;
  172.                fy = u[1] - normal[i][1] * two_nu;
  173.                fz = u[2] - normal[i][2] * two_nu;
  174.                m = 2.0F * GL_SQRT( fx*fx + fy*fy + (fz+1.0)*(fz+1.0) );
  175.                if (m==0.0F) {
  176.                   texcoord[i][1] = 0.5F;
  177.                }
  178.                else {
  179.                   texcoord[i][1] = fy / m + 0.5F;
  180.                }
  181.             }
  182.             break;
  183.          default:
  184.             gl_problem(ctx, "Bad T texgen");
  185.             return;
  186.       }
  187.    }
  188.  
  189.    if (texSet->TexGenEnabled & R_BIT) {
  190.       GLint i;
  191.       switch (texSet->GenModeR) {
  192.          case GL_OBJECT_LINEAR:
  193.             for (i=0;i<n;i++) {
  194.                texcoord[i][2] = DOT4( obj[i], texSet->ObjectPlaneR );
  195.             }
  196.             break;
  197.          case GL_EYE_LINEAR:
  198.             for (i=0;i<n;i++) {
  199.                texcoord[i][2] = DOT4( eye[i], texSet->EyePlaneR );
  200.             }
  201.             break;
  202.          default:
  203.             gl_problem(ctx, "Bad R texgen");
  204.             return;
  205.       }
  206.    }
  207.  
  208.    if (texSet->TexGenEnabled & Q_BIT) {
  209.       GLint i;
  210.       switch (texSet->GenModeQ) {
  211.          case GL_OBJECT_LINEAR:
  212.             for (i=0;i<n;i++) {
  213.                texcoord[i][3] = DOT4( obj[i], texSet->ObjectPlaneQ );
  214.             }
  215.             break;
  216.          case GL_EYE_LINEAR:
  217.             for (i=0;i<n;i++) {
  218.                texcoord[i][3] = DOT4( eye[i], texSet->EyePlaneQ );
  219.             }
  220.             break;
  221.          default:
  222.             gl_problem(ctx, "Bad Q texgen");
  223.             return;
  224.       }
  225.    }
  226. }
  227.  
  228.  
  229.  
  230. /*
  231.  * Paletted texture sampling.
  232.  * Input:  tObj - the texture object
  233.  *         index - the palette index (8-bit only)
  234.  * Output:  red, green, blue, alpha - the texel color
  235.  */
  236. static void palette_sample(const struct gl_texture_object *tObj,
  237.                            GLubyte index, GLubyte rgba[4] )
  238. {
  239.    GLcontext *ctx = gl_get_current_context();  /* THIS IS A HACK */
  240.    GLint i = index;
  241.    const GLubyte *palette;
  242.  
  243.    if (ctx->Texture.SharedPalette) {
  244.       palette = ctx->Texture.Palette;
  245.    }
  246.    else {
  247.       palette = tObj->Palette;
  248.    }
  249.  
  250.    switch (tObj->PaletteFormat) {
  251.       case GL_ALPHA:
  252.          rgba[ACOMP] = tObj->Palette[index];
  253.          return;
  254.       case GL_LUMINANCE:
  255.       case GL_INTENSITY:
  256.          rgba[RCOMP] = palette[index];
  257.          return;
  258.       case GL_LUMINANCE_ALPHA:
  259.          rgba[RCOMP] = palette[(index << 1) + 0];
  260.          rgba[ACOMP] = palette[(index << 1) + 1];
  261.          return;
  262.       case GL_RGB:
  263.          rgba[RCOMP] = palette[index * 3 + 0];
  264.          rgba[GCOMP] = palette[index * 3 + 1];
  265.          rgba[BCOMP] = palette[index * 3 + 2];
  266.          return;
  267.       case GL_RGBA:
  268.          rgba[RCOMP] = palette[(i << 2) + 0];
  269.          rgba[GCOMP] = palette[(i << 2) + 1];
  270.          rgba[BCOMP] = palette[(i << 2) + 2];
  271.          rgba[ACOMP] = palette[(i << 2) + 3];
  272.          return;
  273.       default:
  274.          gl_problem(NULL, "Bad palette format in palette_sample");
  275.    }
  276. }
  277.  
  278.  
  279.  
  280.  
  281. /**********************************************************************/
  282. /*                    1-D Texture Sampling Functions                  */
  283. /**********************************************************************/
  284.  
  285.  
  286. /*
  287.  * Return the fractional part of x.
  288.  */
  289. #define frac(x) ((GLfloat)(x)-floor((GLfloat)x))
  290.  
  291.  
  292.  
  293. /*
  294.  * Given 1-D texture image and an (i) texel column coordinate, return the
  295.  * texel color.
  296.  */
  297. static void get_1d_texel( const struct gl_texture_object *tObj,
  298.                           const struct gl_texture_image *img, GLint i,
  299.                           GLubyte rgba[4] )
  300. {
  301.    GLubyte *texel;
  302.  
  303. #ifdef DEBUG
  304.    GLint width = img->Width;
  305.    if (i<0 || i>=width)  abort();
  306. #endif
  307.  
  308.    switch (img->Format) {
  309.       case GL_COLOR_INDEX:
  310.          {
  311.             GLubyte index = img->Data[i];
  312.             palette_sample(tObj, index, rgba);
  313.             return;
  314.          }
  315.       case GL_ALPHA:
  316.          rgba[ACOMP] = img->Data[ i ];
  317.          return;
  318.       case GL_LUMINANCE:
  319.       case GL_INTENSITY:
  320.          rgba[RCOMP] = img->Data[ i ];
  321.          return;
  322.       case GL_LUMINANCE_ALPHA:
  323.          texel = img->Data + i * 2;
  324.          rgba[RCOMP] = texel[0];
  325.          rgba[ACOMP] = texel[1];
  326.          return;
  327.       case GL_RGB:
  328.          texel = img->Data + i * 3;
  329.          rgba[RCOMP] = texel[0];
  330.          rgba[GCOMP] = texel[1];
  331.          rgba[BCOMP] = texel[2];
  332.          return;
  333.       case GL_RGBA:
  334.          texel = img->Data + i * 4;
  335.          rgba[RCOMP] = texel[0];
  336.          rgba[GCOMP] = texel[1];
  337.          rgba[BCOMP] = texel[2];
  338.          rgba[ACOMP] = texel[3];
  339.          return;
  340.       default:
  341.          gl_problem(NULL, "Bad format in get_1d_texel");
  342.          return;
  343.    }
  344. }
  345.  
  346.  
  347.  
  348. /*
  349.  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  350.  */
  351. static void sample_1d_nearest( const struct gl_texture_object *tObj,
  352.                                const struct gl_texture_image *img,
  353.                                GLfloat s, GLubyte rgba[4] )
  354. {
  355.    GLint width = img->Width2;  /* without border, power of two */
  356.    GLint i;
  357.    GLubyte *texel;
  358.  
  359.    /* Clamp/Repeat S and convert to integer texel coordinate */
  360.    if (tObj->WrapS==GL_REPEAT) {
  361.       /* s limited to [0,1) */
  362.       /* i limited to [0,width-1] */
  363.       i = (GLint) (s * width);
  364.       if (s<0.0F)  i -= 1;
  365.       i &= (width-1);
  366.    }
  367.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  368.       GLfloat min = 1.0F / (2.0F * width);
  369.       GLfloat max = 1.0F - min;
  370.       if (s < min)
  371.          i = 0;
  372.       else if (s > max)
  373.          i = width-1;
  374.       else
  375.          i = (GLint) (s * width);
  376.    }
  377.    else {
  378.       ASSERT(tObj->WrapS==GL_CLAMP);
  379.       /* s limited to [0,1] */
  380.       /* i limited to [0,width-1] */
  381.       if (s<=0.0F)       i = 0;
  382.       else if (s>=1.0F)  i = width-1;
  383.       else               i = (GLint) (s * width);
  384.    }
  385.  
  386.    /* skip over the border, if any */
  387.    i += img->Border;
  388.  
  389.    /* Get the texel */
  390.    switch (img->Format) {
  391.       case GL_COLOR_INDEX:
  392.          {
  393.             GLubyte index = img->Data[i];
  394.             palette_sample(tObj, index, rgba );
  395.             return;
  396.          }
  397.       case GL_ALPHA:
  398.          rgba[ACOMP] = img->Data[i];
  399.          return;
  400.       case GL_LUMINANCE:
  401.       case GL_INTENSITY:
  402.          rgba[RCOMP] = img->Data[i];
  403.          return;
  404.       case GL_LUMINANCE_ALPHA:
  405.          texel = img->Data + i * 2;
  406.          rgba[RCOMP] = texel[0];
  407.          rgba[ACOMP] = texel[1];
  408.          return;
  409.       case GL_RGB:
  410.          texel = img->Data + i * 3;
  411.          rgba[RCOMP] = texel[0];
  412.          rgba[RCOMP] = texel[1];
  413.          rgba[BCOMP] = texel[2];
  414.          return;
  415.       case GL_RGBA:
  416.          texel = img->Data + i * 4;
  417.          rgba[RCOMP] = texel[0];
  418.          rgba[RCOMP] = texel[1];
  419.          rgba[BCOMP] = texel[2];
  420.          rgba[ACOMP] = texel[3];
  421.          return;
  422.       default:
  423.          gl_problem(NULL, "Bad format in sample_1d_nearest");
  424.    }
  425. }
  426.  
  427.  
  428.  
  429. /*
  430.  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  431.  */
  432. static void sample_1d_linear( const struct gl_texture_object *tObj,
  433.                               const struct gl_texture_image *img,
  434.                               GLfloat s,
  435.                               GLubyte rgba[4] )
  436. {
  437.    GLint width = img->Width2;
  438.    GLint i0, i1;
  439.    GLfloat u;
  440.    GLint i0border, i1border;
  441.  
  442.    u = s * width;
  443.    if (tObj->WrapS==GL_REPEAT) {
  444.       i0 = ((GLint) floor(u - 0.5F)) % width;
  445.       i1 = (i0 + 1) & (width-1);
  446.       i0border = i1border = 0;
  447.    }
  448.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  449.       GLfloat min = 1.0F / (2.0F * width);
  450.       GLfloat max = 1.0F - min;
  451.       if (s < min)
  452.          i0 = 0;
  453.       else if (s > max)
  454.          i0 = width-1;
  455.       else
  456.          i0 = (GLint) (s * width);
  457.       i1 = i0 + 1;
  458.       if (i1 >= width)
  459.          i1 = width - 1;
  460.       i0border = i1border = 0;
  461.    }
  462.    else {
  463.       ASSERT(tObj->WrapS==GL_CLAMP);
  464.       if (u < 0.0F)  u = 0.0F;
  465.       else if (u > width)  u = width;
  466.       i0 = (GLint) floor(u - 0.5F);
  467.       i1 = i0 + 1;
  468.       i0border = (i0<0) | (i0>=width);
  469.       i1border = (i1<0) | (i1>=width);
  470.    }
  471.  
  472.    if (img->Border) {
  473.       i0 += img->Border;
  474.       i1 += img->Border;
  475.       i0border = i1border = 0;
  476.    }
  477.    else {
  478.       i0 &= (width-1);
  479.    }
  480.  
  481.    {
  482.       GLfloat a = frac(u - 0.5F);
  483.  
  484.       GLint w0 = (GLint) ((1.0F-a) * 256.0F);
  485.       GLint w1 = (GLint) (      a  * 256.0F);
  486.  
  487.       GLubyte t0[4], t1[4];  /* texels */
  488.  
  489.       if (i0border) {
  490.          t0[RCOMP] = tObj->BorderColor[0];
  491.          t0[GCOMP] = tObj->BorderColor[1];
  492.          t0[BCOMP] = tObj->BorderColor[2];
  493.          t0[ACOMP] = tObj->BorderColor[3];
  494.       }
  495.       else {
  496.          get_1d_texel( tObj, img, i0, t0 );
  497.       }
  498.       if (i1border) {
  499.          t1[RCOMP] = tObj->BorderColor[0];
  500.          t1[GCOMP] = tObj->BorderColor[1];
  501.          t1[BCOMP] = tObj->BorderColor[2];
  502.          t1[ACOMP] = tObj->BorderColor[3];
  503.       }
  504.       else {
  505.          get_1d_texel( tObj, img, i1, t1 );
  506.       }
  507.  
  508.       /* MMX */
  509.       rgba[0] = (w0 * t0[0] + w1 * t1[0]) >> 8;
  510.       rgba[1] = (w0 * t0[1] + w1 * t1[1]) >> 8;
  511.       rgba[2] = (w0 * t0[2] + w1 * t1[2]) >> 8;
  512.       rgba[3] = (w0 * t0[3] + w1 * t1[3]) >> 8;
  513.    }
  514. }
  515.  
  516.  
  517. static void
  518. sample_1d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  519.                                   GLfloat s, GLfloat lambda,
  520.                                   GLubyte rgba[4] )
  521. {
  522.    GLint level;
  523.    if (lambda <= 0.5F)
  524.       lambda = 0.0F;
  525.    else if (lambda > tObj->M + 0.4999F)
  526.       lambda = tObj->M + 0.4999F;
  527.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  528.    if (level > tObj->P)
  529.       level = tObj->P;
  530.  
  531.    sample_1d_nearest( tObj, tObj->Image[level], s, rgba );
  532. }
  533.  
  534.  
  535. static void
  536. sample_1d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  537.                                  GLfloat s, GLfloat lambda,
  538.                                  GLubyte rgba[4] )
  539. {
  540.    GLint level;
  541.    if (lambda <= 0.5F)
  542.       lambda = 0.0F;
  543.    else if (lambda > tObj->M + 0.4999F)
  544.       lambda = tObj->M + 0.4999F;
  545.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  546.    if (level > tObj->P)
  547.       level = tObj->P;
  548.  
  549.    sample_1d_linear( tObj, tObj->Image[level], s, rgba );
  550. }
  551.  
  552.  
  553.  
  554. static void
  555. sample_1d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  556.                                  GLfloat s, GLfloat lambda,
  557.                                  GLubyte rgba[4] )
  558. {
  559.    GLint level;
  560.    if (lambda < 0.0F)
  561.       lambda = 0.0F;
  562.    else if (lambda > tObj->M)
  563.       lambda = tObj->M;
  564.    level = (GLint) (tObj->BaseLevel + lambda);
  565.  
  566.    if (level >= tObj->P) {
  567.       sample_1d_nearest( tObj, tObj->Image[tObj->P], s, rgba );
  568.    }
  569.    else {
  570.       GLubyte t0[4], t1[4];
  571.       GLfloat f = frac(lambda);
  572.       sample_1d_nearest( tObj, tObj->Image[level  ], s, t0 );
  573.       sample_1d_nearest( tObj, tObj->Image[level+1], s, t1 );
  574.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  575.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  576.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  577.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  578.    }
  579. }
  580.  
  581.  
  582.  
  583. static void
  584. sample_1d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  585.                                 GLfloat s, GLfloat lambda,
  586.                                 GLubyte rgba[4] )
  587. {
  588.    GLint level;
  589.    if (lambda < 0.0F)
  590.       lambda = 0.0F;
  591.    else if (lambda > tObj->M)
  592.       lambda = tObj->M;
  593.    level = (GLint) (tObj->BaseLevel + lambda);
  594.  
  595.    if (level >= tObj->P) {
  596.       sample_1d_linear( tObj, tObj->Image[tObj->P], s, rgba );
  597.    }
  598.    else {
  599.       GLubyte t0[4], t1[4];
  600.       GLfloat f = frac(lambda);
  601.       sample_1d_linear( tObj, tObj->Image[level  ], s, t0 );
  602.       sample_1d_linear( tObj, tObj->Image[level+1], s, t1 );
  603.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  604.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  605.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  606.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  607.    }
  608. }
  609.  
  610.  
  611.  
  612. static void sample_nearest_1d( const struct gl_texture_object *tObj, GLuint n,
  613.                                const GLfloat s[], const GLfloat t[],
  614.                                const GLfloat u[], const GLfloat lambda[],
  615.                                GLubyte rgba[][4] )
  616. {
  617.    GLuint i;
  618.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  619.    (void) t;
  620.    (void) u;
  621.    (void) lambda;
  622.    for (i=0;i<n;i++) {
  623.       sample_1d_nearest( tObj, image, s[i], rgba[i] );
  624.    }
  625. }
  626.  
  627.  
  628.  
  629. static void sample_linear_1d( const struct gl_texture_object *tObj, GLuint n,
  630.                               const GLfloat s[], const GLfloat t[],
  631.                               const GLfloat u[], const GLfloat lambda[],
  632.                               GLubyte rgba[][4] )
  633. {
  634.    GLuint i;
  635.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  636.    (void) t;
  637.    (void) u;
  638.    (void) lambda;
  639.    for (i=0;i<n;i++) {
  640.       sample_1d_linear( tObj, image, s[i], rgba[i] );
  641.    }
  642. }
  643.  
  644.  
  645. /*
  646.  * Given an (s) texture coordinate and lambda (level of detail) value,
  647.  * return a texture sample.
  648.  *
  649.  */
  650. static void sample_lambda_1d( const struct gl_texture_object *tObj, GLuint n,
  651.                               const GLfloat s[], const GLfloat t[],
  652.                               const GLfloat u[], const GLfloat lambda[],
  653.                               GLubyte rgba[][4] )
  654. {
  655.    GLuint i;
  656.  
  657.    (void) t;
  658.    (void) u;
  659.  
  660.    for (i=0;i<n;i++) {
  661.       if (lambda[i] > tObj->MinMagThresh) {
  662.          /* minification */
  663.          switch (tObj->MinFilter) {
  664.             case GL_NEAREST:
  665.                sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
  666.                break;
  667.             case GL_LINEAR:
  668.                sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
  669.                break;
  670.             case GL_NEAREST_MIPMAP_NEAREST:
  671.                sample_1d_nearest_mipmap_nearest( tObj, lambda[i], s[i], rgba[i] );
  672.                break;
  673.             case GL_LINEAR_MIPMAP_NEAREST:
  674.                sample_1d_linear_mipmap_nearest( tObj, s[i], lambda[i], rgba[i] );
  675.                break;
  676.             case GL_NEAREST_MIPMAP_LINEAR:
  677.                sample_1d_nearest_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
  678.                break;
  679.             case GL_LINEAR_MIPMAP_LINEAR:
  680.                sample_1d_linear_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
  681.                break;
  682.             default:
  683.                gl_problem(NULL, "Bad min filter in sample_1d_texture");
  684.                return;
  685.          }
  686.       }
  687.       else {
  688.          /* magnification */
  689.          switch (tObj->MagFilter) {
  690.             case GL_NEAREST:
  691.                sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
  692.                break;
  693.             case GL_LINEAR:
  694.                sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
  695.                break;
  696.             default:
  697.                gl_problem(NULL, "Bad mag filter in sample_1d_texture");
  698.                return;
  699.          }
  700.       }
  701.    }
  702. }
  703.  
  704.  
  705.  
  706.  
  707. /**********************************************************************/
  708. /*                    2-D Texture Sampling Functions                  */
  709. /**********************************************************************/
  710.  
  711.  
  712. /*
  713.  * Given a texture image and an (i,j) integer texel coordinate, return the
  714.  * texel color.
  715.  */
  716. static void get_2d_texel( const struct gl_texture_object *tObj,
  717.                           const struct gl_texture_image *img, GLint i, GLint j,
  718.                           GLubyte rgba[4] )
  719. {
  720.    GLint width = img->Width;    /* includes border */
  721.    GLubyte *texel;
  722.  
  723. #ifdef DEBUG
  724.    GLint height = img->Height;  /* includes border */
  725.    if (i<0 || i>=width)  abort();
  726.    if (j<0 || j>=height)  abort();
  727. #endif
  728.  
  729.    switch (img->Format) {
  730.       case GL_COLOR_INDEX:
  731.          {
  732.             GLubyte index = img->Data[ width *j + i ];
  733.             palette_sample(tObj, index, rgba );
  734.             return;
  735.          }
  736.       case GL_ALPHA:
  737.          rgba[ACOMP] = img->Data[ width * j + i ];
  738.          return;
  739.       case GL_LUMINANCE:
  740.       case GL_INTENSITY:
  741.          rgba[RCOMP] = img->Data[ width * j + i ];
  742.          return;
  743.       case GL_LUMINANCE_ALPHA:
  744.          texel = img->Data + (width * j + i) * 2;
  745.          rgba[RCOMP] = texel[0];
  746.          rgba[ACOMP] = texel[1];
  747.          return;
  748.       case GL_RGB:
  749.          texel = img->Data + (width * j + i) * 3;
  750.          rgba[RCOMP] = texel[0];
  751.          rgba[GCOMP] = texel[1];
  752.          rgba[BCOMP] = texel[2];
  753.          return;
  754.       case GL_RGBA:
  755.          texel = img->Data + (width * j + i) * 4;
  756.          rgba[RCOMP] = texel[0];
  757.          rgba[GCOMP] = texel[1];
  758.          rgba[BCOMP] = texel[2];
  759.          rgba[ACOMP] = texel[3];
  760.          return;
  761.       default:
  762.          gl_problem(NULL, "Bad format in get_2d_texel");
  763.    }
  764. }
  765.  
  766.  
  767.  
  768. /*
  769.  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  770.  */
  771. static void sample_2d_nearest( const struct gl_texture_object *tObj,
  772.                                const struct gl_texture_image *img,
  773.                                GLfloat s, GLfloat t,
  774.                                GLubyte rgba[] )
  775. {
  776.    GLint imgWidth = img->Width;  /* includes border */
  777.    GLint width = img->Width2;    /* without border, power of two */
  778.    GLint height = img->Height2;  /* without border, power of two */
  779.    GLint i, j;
  780.    GLubyte *texel;
  781.  
  782.    /* Clamp/Repeat S and convert to integer texel coordinate */
  783.    if (tObj->WrapS==GL_REPEAT) {
  784.       /* s limited to [0,1) */
  785.       /* i limited to [0,width-1] */
  786.       i = (GLint) (s * width);
  787.       if (s<0.0F)  i -= 1;
  788.       i &= (width-1);
  789.    }
  790.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  791.       GLfloat min = 1.0F / (2.0F * width);
  792.       GLfloat max = 1.0F - min;
  793.       if (s < min)
  794.          i = 0;
  795.       else if (s > max)
  796.          i = width-1;
  797.       else
  798.          i = (GLint) (s * width);
  799.    }
  800.    else {
  801.       ASSERT(tObj->WrapS==GL_CLAMP);
  802.       /* s limited to [0,1] */
  803.       /* i limited to [0,width-1] */
  804.       if (s<=0.0F)      i = 0;
  805.       else if (s>=1.0F) i = width-1;
  806.       else              i = (GLint) (s * width);
  807.    }
  808.  
  809.    /* Clamp/Repeat T and convert to integer texel coordinate */
  810.    if (tObj->WrapT==GL_REPEAT) {
  811.       /* t limited to [0,1) */
  812.       /* j limited to [0,height-1] */
  813.       j = (GLint) (t * height);
  814.       if (t<0.0F)  j -= 1;
  815.       j &= (height-1);
  816.    }
  817.    else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
  818.       GLfloat min = 1.0F / (2.0F * height);
  819.       GLfloat max = 1.0F - min;
  820.       if (t < min)
  821.          j = 0;
  822.       else if (t > max)
  823.          j = height-1;
  824.       else
  825.          j = (GLint) (t * height);
  826.    }
  827.    else {
  828.       ASSERT(tObj->WrapT==GL_CLAMP);
  829.       /* t limited to [0,1] */
  830.       /* j limited to [0,height-1] */
  831.       if (t<=0.0F)      j = 0;
  832.       else if (t>=1.0F) j = height-1;
  833.       else              j = (GLint) (t * height);
  834.    }
  835.  
  836.    /* skip over the border, if any */
  837.    i += img->Border;
  838.    j += img->Border;
  839.  
  840.    switch (img->Format) {
  841.       case GL_COLOR_INDEX:
  842.          {
  843.             GLubyte index = img->Data[ j * imgWidth + i ];
  844.             palette_sample(tObj, index, rgba);
  845.             return;
  846.          }
  847.       case GL_ALPHA:
  848.          rgba[ACOMP] = img->Data[ j * imgWidth + i ];
  849.          return;
  850.       case GL_LUMINANCE:
  851.       case GL_INTENSITY:
  852.          rgba[RCOMP] = img->Data[ j * imgWidth + i ];
  853.          return;
  854.       case GL_LUMINANCE_ALPHA:
  855.          texel = img->Data + ((j * imgWidth + i) << 1);
  856.          rgba[RCOMP] = texel[0];
  857.          rgba[ACOMP] = texel[1];
  858.          return;
  859.       case GL_RGB:
  860.          texel = img->Data + (j * imgWidth + i) * 3;
  861.          rgba[RCOMP] = texel[0];
  862.          rgba[GCOMP] = texel[1];
  863.          rgba[BCOMP] = texel[2];
  864.          return;
  865.       case GL_RGBA:
  866.          texel = img->Data + ((j * imgWidth + i) << 2);
  867.          rgba[RCOMP] = texel[0];
  868.          rgba[GCOMP] = texel[1];
  869.          rgba[BCOMP] = texel[2];
  870.          rgba[ACOMP] = texel[3];
  871.          return;
  872.       default:
  873.          gl_problem(NULL, "Bad format in sample_2d_nearest");
  874.    }
  875. }
  876.  
  877.  
  878.  
  879. /*
  880.  * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
  881.  */
  882. static void sample_2d_linear( const struct gl_texture_object *tObj,
  883.                               const struct gl_texture_image *img,
  884.                               GLfloat s, GLfloat t,
  885.                               GLubyte rgba[] )
  886. {
  887.    GLint width = img->Width2;
  888.    GLint height = img->Height2;
  889.    GLint i0, j0, i1, j1;
  890.    GLint i0border, j0border, i1border, j1border;
  891.    GLfloat u, v;
  892.  
  893.    u = s * width;
  894.    if (tObj->WrapS==GL_REPEAT) {
  895.       i0 = ((GLint) floor(u - 0.5F)) % width;
  896.       i1 = (i0 + 1) & (width-1);
  897.       i0border = i1border = 0;
  898.    }
  899.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  900.       GLfloat min = 1.0F / (2.0F * width);
  901.       GLfloat max = 1.0F - min;
  902.       if (s < min)
  903.          i0 = 0;
  904.       else if (s > max)
  905.          i0 = width-1;
  906.       else
  907.          i0 = (GLint) (s * width);
  908.       i1 = i0 + 1;
  909.       if (i1 >= width)
  910.          i1 = width - 1;
  911.       i0border = i1border = 0;
  912.    }
  913.    else {
  914.       ASSERT(tObj->WrapS==GL_CLAMP);
  915.       if (u < 0.0F)  u = 0.0F;
  916.       else if (u > width)  u = width;
  917.       i0 = (GLint) floor(u - 0.5F);
  918.       i1 = i0 + 1;
  919.       i0border = (i0<0) | (i0>=width);
  920.       i1border = (i1<0) | (i1>=width);
  921.    }
  922.  
  923.    v = t * height;
  924.    if (tObj->WrapT==GL_REPEAT) {
  925.       j0 = ((GLint) floor(v - 0.5F)) % height;
  926.       j1 = (j0 + 1) & (height-1);
  927.       j0border = j1border = 0;
  928.    }
  929.    else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
  930.       GLfloat min = 1.0F / (2.0F * height);
  931.       GLfloat max = 1.0F - min;
  932.       if (t < min)
  933.          j0 = 0;
  934.       else if (t > max)
  935.          j0 = height-1;
  936.       else
  937.          j0 = (GLint) (t * height);
  938.       j1 = j0 + 1;
  939.       if (j1 >= height)
  940.          j1 = height - 1;
  941.       j0border = j1border = 0;
  942.    }
  943.    else {
  944.       ASSERT(tObj->WrapT==GL_CLAMP);
  945.       if (v < 0.0F)  v = 0.0F;
  946.       else if (v > height)  v = height;
  947.       j0 = (GLint) floor(v - 0.5F );
  948.       j1 = j0 + 1;
  949.       j0border = (j0<0) | (j0>=height);
  950.       j1border = (j1<0) | (j1>=height);
  951.    }
  952.  
  953.    if (img->Border) {
  954.       i0 += img->Border;
  955.       i1 += img->Border;
  956.       j0 += img->Border;
  957.       j1 += img->Border;
  958.       i0border = i1border = 0;
  959.       j0border = j1border = 0;
  960.    }
  961.    else {
  962.       i0 &= (width-1);
  963.       j0 &= (height-1);
  964.    }
  965.  
  966.    {
  967.       GLfloat a = frac(u - 0.5F);
  968.       GLfloat b = frac(v - 0.5F);
  969.  
  970.       GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * 256.0F);
  971.       GLint w10 = (GLint) (      a *(1.0F-b) * 256.0F);
  972.       GLint w01 = (GLint) ((1.0F-a)*      b  * 256.0F);
  973.       GLint w11 = (GLint) (      a *      b  * 256.0F);
  974.  
  975.       GLubyte t00[4];
  976.       GLubyte t10[4];
  977.       GLubyte t01[4];
  978.       GLubyte t11[4];
  979.  
  980.       if (i0border | j0border) {
  981.          t00[RCOMP] = tObj->BorderColor[0];
  982.          t00[GCOMP] = tObj->BorderColor[1];
  983.          t00[BCOMP] = tObj->BorderColor[2];
  984.          t00[ACOMP] = tObj->BorderColor[3];
  985.       }
  986.       else {
  987.          get_2d_texel( tObj, img, i0, j0, t00 );
  988.       }
  989.       if (i1border | j0border) {
  990.          t10[RCOMP] = tObj->BorderColor[0];
  991.          t10[GCOMP] = tObj->BorderColor[1];
  992.          t10[BCOMP] = tObj->BorderColor[2];
  993.          t10[ACOMP] = tObj->BorderColor[3];
  994.       }
  995.       else {
  996.          get_2d_texel( tObj, img, i1, j0, t10 );
  997.       }
  998.       if (i0border | j1border) {
  999.          t01[RCOMP] = tObj->BorderColor[0];
  1000.          t01[GCOMP] = tObj->BorderColor[1];
  1001.          t01[BCOMP] = tObj->BorderColor[2];
  1002.          t01[ACOMP] = tObj->BorderColor[3];
  1003.       }
  1004.       else {
  1005.          get_2d_texel( tObj, img, i0, j1, t01 );
  1006.       }
  1007.       if (i1border | j1border) {
  1008.          t11[RCOMP] = tObj->BorderColor[0];
  1009.          t11[GCOMP] = tObj->BorderColor[1];
  1010.          t11[BCOMP] = tObj->BorderColor[2];
  1011.          t11[ACOMP] = tObj->BorderColor[3];
  1012.       }
  1013.       else {
  1014.          get_2d_texel( tObj, img, i1, j1, t11 );
  1015.       }
  1016.  
  1017.       /* MMX */
  1018.       rgba[0] = (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> 8;
  1019.       rgba[1] = (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> 8;
  1020.       rgba[2] = (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> 8;
  1021.       rgba[3] = (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> 8;
  1022.    }
  1023. }
  1024.  
  1025.  
  1026.  
  1027. static void
  1028. sample_2d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  1029.                                   GLfloat s, GLfloat t, GLfloat lambda,
  1030.                                   GLubyte rgba[4] )
  1031. {
  1032.    GLint level;
  1033.    if (lambda <= 0.5F)
  1034.       lambda = 0.0F;
  1035.    else if (lambda > tObj->M + 0.4999F)
  1036.       lambda = tObj->M + 0.4999F;
  1037.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  1038.    if (level > tObj->P)
  1039.       level = tObj->P;
  1040.  
  1041.    sample_2d_nearest( tObj, tObj->Image[level], s, t, rgba );
  1042. }
  1043.  
  1044.  
  1045.  
  1046. static void
  1047. sample_2d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  1048.                                  GLfloat s, GLfloat t, GLfloat lambda,
  1049.                                  GLubyte rgba[4] )
  1050. {
  1051.    GLint level;
  1052.    if (lambda <= 0.5F)
  1053.       lambda = 0.0F;
  1054.    else if (lambda > tObj->M + 0.4999F)
  1055.       lambda = tObj->M + 0.4999F;
  1056.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  1057.    if (level > tObj->P)
  1058.       level = tObj->P;
  1059.  
  1060.    sample_2d_linear( tObj, tObj->Image[level], s, t, rgba );
  1061. }
  1062.  
  1063.  
  1064.  
  1065. static void
  1066. sample_2d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  1067.                                  GLfloat s, GLfloat t, GLfloat lambda,
  1068.                                  GLubyte rgba[4] )
  1069. {
  1070.    GLint level;
  1071.    if (lambda < 0.0F)
  1072.       lambda = 0.0F;
  1073.    else if (lambda > tObj->M)
  1074.       lambda = tObj->M;
  1075.    level = (GLint) (tObj->BaseLevel + lambda);
  1076.  
  1077.    if (level >= tObj->P) {
  1078.       sample_2d_nearest( tObj, tObj->Image[tObj->P], s, t, rgba );
  1079.    }
  1080.    else {
  1081.       GLubyte t0[4], t1[4];  /* texels */
  1082.       GLfloat f = frac(lambda);
  1083.       sample_2d_nearest( tObj, tObj->Image[level  ], s, t, t0 );
  1084.       sample_2d_nearest( tObj, tObj->Image[level+1], s, t, t1 );
  1085.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1086.       rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1087.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1088.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1089.    }
  1090. }
  1091.  
  1092.  
  1093.  
  1094. static void
  1095. sample_2d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  1096.                                 GLfloat s, GLfloat t, GLfloat lambda,
  1097.                                 GLubyte rgba[4] )
  1098. {
  1099.    GLint level;
  1100.    if (lambda < 0.0F)
  1101.       lambda = 0.0F;
  1102.    else if (lambda > tObj->M)
  1103.       lambda = tObj->M;
  1104.    level = (GLint) (tObj->BaseLevel + lambda);
  1105.  
  1106.    if (level >= tObj->P) {
  1107.       sample_2d_linear( tObj, tObj->Image[tObj->P], s, t, rgba );
  1108.    }
  1109.    else {
  1110.       GLubyte t0[4], t1[4];  /* texels */
  1111.       GLfloat f = frac(lambda);
  1112.       sample_2d_linear( tObj, tObj->Image[level  ], s, t, t0 );
  1113.       sample_2d_linear( tObj, tObj->Image[level+1], s, t, t1 );
  1114.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1115.       rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1116.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1117.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1118.    }
  1119. }
  1120.  
  1121.  
  1122.  
  1123. static void sample_nearest_2d( const struct gl_texture_object *tObj, GLuint n,
  1124.                                const GLfloat s[], const GLfloat t[],
  1125.                                const GLfloat u[], const GLfloat lambda[],
  1126.                                GLubyte rgba[][4] )
  1127. {
  1128.    GLuint i;
  1129.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1130.    (void) u;
  1131.    (void) lambda;
  1132.    for (i=0;i<n;i++) {
  1133.       sample_2d_nearest( tObj, image, s[i], t[i], rgba[i] );
  1134.    }
  1135. }
  1136.  
  1137.  
  1138.  
  1139. static void sample_linear_2d( const struct gl_texture_object *tObj, GLuint n,
  1140.                               const GLfloat s[], const GLfloat t[],
  1141.                               const GLfloat u[], const GLfloat lambda[],
  1142.                               GLubyte rgba[][4] )
  1143. {
  1144.    GLuint i;
  1145.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1146.    (void) u;
  1147.    (void) lambda;
  1148.    for (i=0;i<n;i++) {
  1149.       sample_2d_linear( tObj, image, s[i], t[i], rgba[i] );
  1150.    }
  1151. }
  1152.  
  1153.  
  1154. /*
  1155.  * Given an (s,t) texture coordinate and lambda (level of detail) value,
  1156.  * return a texture sample.
  1157.  */
  1158. static void sample_lambda_2d( const struct gl_texture_object *tObj,
  1159.                               GLuint n,
  1160.                               const GLfloat s[], const GLfloat t[],
  1161.                               const GLfloat u[], const GLfloat lambda[],
  1162.                               GLubyte rgba[][4] )
  1163. {
  1164.    GLuint i;
  1165.    (void) u;
  1166.    for (i=0;i<n;i++) {
  1167.       if (lambda[i] > tObj->MinMagThresh) {
  1168.          /* minification */
  1169.          switch (tObj->MinFilter) {
  1170.             case GL_NEAREST:
  1171.                sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
  1172.                break;
  1173.             case GL_LINEAR:
  1174.                sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
  1175.                break;
  1176.             case GL_NEAREST_MIPMAP_NEAREST:
  1177.                sample_2d_nearest_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
  1178.                break;
  1179.             case GL_LINEAR_MIPMAP_NEAREST:
  1180.                sample_2d_linear_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
  1181.                break;
  1182.             case GL_NEAREST_MIPMAP_LINEAR:
  1183.                sample_2d_nearest_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
  1184.                break;
  1185.             case GL_LINEAR_MIPMAP_LINEAR:
  1186.                sample_2d_linear_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
  1187.                break;
  1188.             default:
  1189.                gl_problem(NULL, "Bad min filter in sample_2d_texture");
  1190.                return;
  1191.          }
  1192.       }
  1193.       else {
  1194.          /* magnification */
  1195.          switch (tObj->MagFilter) {
  1196.             case GL_NEAREST:
  1197.                sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
  1198.                break;
  1199.             case GL_LINEAR:
  1200.                sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
  1201.                break;
  1202.             default:
  1203.                gl_problem(NULL, "Bad mag filter in sample_2d_texture");
  1204.          }
  1205.       }
  1206.    }
  1207. }
  1208.  
  1209.  
  1210. /*
  1211.  * Optimized 2-D texture sampling:
  1212.  *    S and T wrap mode == GL_REPEAT
  1213.  *    No border
  1214.  *    Format = GL_RGB
  1215.  */
  1216. static void opt_sample_rgb_2d( const struct gl_texture_object *tObj,
  1217.                                GLuint n, const GLfloat s[], const GLfloat t[],
  1218.                                const GLfloat u[], const GLfloat lambda[],
  1219.                                GLubyte rgba[][4] )
  1220. {
  1221.    const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
  1222.    GLfloat width = img->Width, height = img->Height;
  1223.    GLint colMask = img->Width-1, rowMask = img->Height-1;
  1224.    GLint shift = img->WidthLog2;
  1225.    GLuint k;
  1226.    (void) u;
  1227.    (void) lambda;
  1228.    ASSERT(tObj->WrapS==GL_REPEAT);
  1229.    ASSERT(tObj->WrapT==GL_REPEAT);
  1230.    ASSERT(img->Border==0);
  1231.    ASSERT(img->Format==GL_RGB);
  1232.  
  1233.    for (k=0;k<n;k++) {
  1234.       GLint i = (GLint) (s[k] * width) & colMask;
  1235.       GLint j = (GLint) (t[k] * height) & rowMask;
  1236.       GLint pos = (j << shift) | i;
  1237.       GLubyte *texel = img->Data + pos + pos + pos;  /* pos*3 */
  1238.       rgba[k][RCOMP] = texel[0];
  1239.       rgba[k][GCOMP] = texel[1];
  1240.       rgba[k][BCOMP] = texel[2];
  1241.    }
  1242. }
  1243.  
  1244.  
  1245. /*
  1246.  * Optimized 2-D texture sampling:
  1247.  *    S and T wrap mode == GL_REPEAT
  1248.  *    No border
  1249.  *    Format = GL_RGBA
  1250.  */
  1251. static void opt_sample_rgba_2d( const struct gl_texture_object *tObj,
  1252.                                 GLuint n, const GLfloat s[], const GLfloat t[],
  1253.                                 const GLfloat u[], const GLfloat lambda[],
  1254.                                 GLubyte rgba[][4] )
  1255. {
  1256.    const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
  1257.    GLfloat width = img->Width, height = img->Height;
  1258.    GLint colMask = img->Width-1, rowMask = img->Height-1;
  1259.    GLint shift = img->WidthLog2;
  1260.    GLuint k;
  1261.    (void) u;
  1262.    (void) lambda;
  1263.  
  1264.    ASSERT(tObj->WrapS==GL_REPEAT);
  1265.    ASSERT(tObj->WrapT==GL_REPEAT);
  1266.    ASSERT(img->Border==0);
  1267.    ASSERT(img->Format==GL_RGBA);
  1268.  
  1269.    for (k=0;k<n;k++) {
  1270.       GLint i = (GLint) (s[k] * width) & colMask;
  1271.       GLint j = (GLint) (t[k] * height) & rowMask;
  1272.       GLint pos = (j << shift) | i;
  1273.       GLubyte *texel = img->Data + (pos << 2);    /* pos*4 */
  1274.       rgba[k][RCOMP] = texel[0];
  1275.       rgba[k][GCOMP] = texel[1];
  1276.       rgba[k][BCOMP] = texel[2];
  1277.       rgba[k][ACOMP] = texel[3];
  1278.    }
  1279. }
  1280.  
  1281.  
  1282.  
  1283. /**********************************************************************/
  1284. /*                    3-D Texture Sampling Functions                  */
  1285. /**********************************************************************/
  1286.  
  1287. /*
  1288.  * Given a texture image and an (i,j,k) integer texel coordinate, return the
  1289.  * texel color.
  1290.  */
  1291. static void get_3d_texel( const struct gl_texture_object *tObj,
  1292.                           const struct gl_texture_image *img,
  1293.                           GLint i, GLint j, GLint k,
  1294.                           GLubyte rgba[4] )
  1295. {
  1296.    GLint width = img->Width;    /* includes border */
  1297.    GLint height = img->Height;  /* includes border */
  1298.    GLint depth = img->Depth;    /* includes border */
  1299.    GLint rectarea;              /* = width * heigth */
  1300.    GLubyte *texel;
  1301.  
  1302.    rectarea = width*height;
  1303.  
  1304. #ifdef DEBUG
  1305.    if (i<0 || i>=width)  abort();
  1306.    if (j<0 || j>=height)  abort();
  1307.    if (k<0 || k>=depth)  abort();
  1308. #else
  1309.    (void) depth;
  1310. #endif
  1311.  
  1312.    switch (img->Format) {
  1313.       case GL_COLOR_INDEX:
  1314.          {
  1315.             GLubyte index = img->Data[ rectarea * k +  width * j + i ];
  1316.             palette_sample(tObj, index, rgba );
  1317.             return;
  1318.          }
  1319.       case GL_ALPHA:
  1320.          rgba[ACOMP] = img->Data[ rectarea * k +  width * j + i ];
  1321.          return;
  1322.       case GL_LUMINANCE:
  1323.       case GL_INTENSITY:
  1324.          rgba[RCOMP] = img->Data[ rectarea * k +  width * j + i ];
  1325.          return;
  1326.       case GL_LUMINANCE_ALPHA:
  1327.          texel = img->Data + ( rectarea * k + width * j + i) * 2;
  1328.          rgba[RCOMP] = texel[0];
  1329.          rgba[ACOMP] = texel[1];
  1330.          return;
  1331.       case GL_RGB:
  1332.          texel = img->Data + (rectarea * k + width * j + i) * 3;
  1333.          rgba[RCOMP] = texel[0];
  1334.          rgba[GCOMP] = texel[1];
  1335.          rgba[BCOMP] = texel[2];
  1336.          return;
  1337.       case GL_RGBA:
  1338.          texel = img->Data + (rectarea * k + width * j + i) * 4;
  1339.          rgba[RCOMP] = texel[0];
  1340.          rgba[GCOMP] = texel[1];
  1341.          rgba[BCOMP] = texel[2];
  1342.          rgba[ACOMP] = texel[3];
  1343.          return;
  1344.       default:
  1345.          gl_problem(NULL, "Bad format in get_3d_texel");
  1346.    }
  1347. }
  1348.  
  1349.  
  1350. /*
  1351.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  1352.  */
  1353. static void sample_3d_nearest( const struct gl_texture_object *tObj,
  1354.                                const struct gl_texture_image *img,
  1355.                                GLfloat s, GLfloat t, GLfloat r,
  1356.                                GLubyte rgba[4] )
  1357. {
  1358.    GLint imgWidth = img->Width;   /* includes border, if any */
  1359.    GLint imgHeight = img->Height; /* includes border, if any */
  1360.    GLint width = img->Width2;     /* without border, power of two */
  1361.    GLint height = img->Height2;   /* without border, power of two */
  1362.    GLint depth = img->Depth2;     /* without border, power of two */
  1363.    GLint rectarea;                /* = width * height */
  1364.    GLint i, j, k;
  1365.    GLubyte *texel;
  1366.  
  1367.    rectarea = imgWidth * imgHeight;
  1368.  
  1369.    /* Clamp/Repeat S and convert to integer texel coordinate */
  1370.    if (tObj->WrapS==GL_REPEAT) {
  1371.       /* s limited to [0,1) */
  1372.       /* i limited to [0,width-1] */
  1373.       i = (GLint) (s * width);
  1374.       if (s<0.0F)  i -= 1;
  1375.       i &= (width-1);
  1376.    }
  1377.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  1378.       GLfloat min = 1.0F / (2.0F * width);
  1379.       GLfloat max = 1.0F - min;
  1380.       if (s < min)
  1381.          i = 0;
  1382.       else if (s > max)
  1383.          i = width-1;
  1384.       else
  1385.          i = (GLint) (s * width);
  1386.    }
  1387.    else {
  1388.       ASSERT(tObj->WrapS==GL_CLAMP);
  1389.       /* s limited to [0,1] */
  1390.       /* i limited to [0,width-1] */
  1391.       if (s<=0.0F)      i = 0;
  1392.       else if (s>=1.0F) i = width-1;
  1393.       else              i = (GLint) (s * width);
  1394.    }
  1395.  
  1396.    /* Clamp/Repeat T and convert to integer texel coordinate */
  1397.    if (tObj->WrapT==GL_REPEAT) {
  1398.       /* t limited to [0,1) */
  1399.       /* j limited to [0,height-1] */
  1400.       j = (GLint) (t * height);
  1401.       if (t<0.0F)  j -= 1;
  1402.       j &= (height-1);
  1403.    }
  1404.    else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
  1405.       GLfloat min = 1.0F / (2.0F * height);
  1406.       GLfloat max = 1.0F - min;
  1407.       if (t < min)
  1408.          j = 0;
  1409.       else if (t > max)
  1410.          j = height-1;
  1411.       else
  1412.          j = (GLint) (t * height);
  1413.    }
  1414.    else {
  1415.       ASSERT(tObj->WrapT==GL_CLAMP);
  1416.       /* t limited to [0,1] */
  1417.       /* j limited to [0,height-1] */
  1418.       if (t<=0.0F)      j = 0;
  1419.       else if (t>=1.0F) j = height-1;
  1420.       else              j = (GLint) (t * height);
  1421.    }
  1422.  
  1423.    /* Clamp/Repeat R and convert to integer texel coordinate */
  1424.    if (tObj->WrapR==GL_REPEAT) {
  1425.       /* r limited to [0,1) */
  1426.       /* k limited to [0,depth-1] */
  1427.       k = (GLint) (r * depth);
  1428.       if (r<0.0F)  k -= 1;
  1429.       k &= (depth-1);
  1430.    }
  1431.    else if (tObj->WrapR==GL_CLAMP_TO_EDGE) {
  1432.       GLfloat min = 1.0F / (2.0F * depth);
  1433.       GLfloat max = 1.0F - min;
  1434.       if (r < min)
  1435.          k = 0;
  1436.       else if (r > max)
  1437.          k = depth-1;
  1438.       else
  1439.          k = (GLint) (t * depth);
  1440.    }
  1441.    else {
  1442.       ASSERT(tObj->WrapR==GL_CLAMP);
  1443.       /* r limited to [0,1] */
  1444.       /* k limited to [0,depth-1] */
  1445.       if (r<=0.0F)      k = 0;
  1446.       else if (r>=1.0F) k = depth-1;
  1447.       else              k = (GLint) (r * depth);
  1448.    }
  1449.  
  1450.    switch (tObj->Image[0]->Format) {
  1451.       case GL_COLOR_INDEX:
  1452.          {
  1453.             GLubyte index = img->Data[ rectarea * k + j * imgWidth + i ];
  1454.             palette_sample(tObj, index, rgba );
  1455.             return;
  1456.          }
  1457.       case GL_ALPHA:
  1458.          rgba[ACOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
  1459.          return;
  1460.       case GL_LUMINANCE:
  1461.       case GL_INTENSITY:
  1462.          rgba[RCOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
  1463.          return;
  1464.       case GL_LUMINANCE_ALPHA:
  1465.          texel = img->Data + ((rectarea * k + j * imgWidth + i) << 1);
  1466.          rgba[RCOMP] = texel[0];
  1467.          rgba[ACOMP] = texel[1];
  1468.          return;
  1469.       case GL_RGB:
  1470.          texel = img->Data + ( rectarea * k + j * imgWidth + i) * 3;
  1471.          rgba[RCOMP] = texel[0];
  1472.          rgba[GCOMP] = texel[1];
  1473.          rgba[BCOMP] = texel[2];
  1474.          return;
  1475.       case GL_RGBA:
  1476.          texel = img->Data + ((rectarea * k + j * imgWidth + i) << 2);
  1477.          rgba[RCOMP] = texel[0];
  1478.          rgba[GCOMP] = texel[1];
  1479.          rgba[BCOMP] = texel[2];
  1480.          rgba[ACOMP] = texel[3];
  1481.          return;
  1482.       default:
  1483.          gl_problem(NULL, "Bad format in sample_3d_nearest");
  1484.    }
  1485. }
  1486.  
  1487.  
  1488. /*
  1489.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  1490.  */
  1491. static void sample_3d_linear( const struct gl_texture_object *tObj,
  1492.                               const struct gl_texture_image *img,
  1493.                               GLfloat s, GLfloat t, GLfloat r,
  1494.                               GLubyte rgba[4] )
  1495. {
  1496.    GLint width = img->Width2;
  1497.    GLint height = img->Height2;
  1498.    GLint depth = img->Depth2;
  1499.    GLint i0, j0, k0, i1, j1, k1;
  1500.    GLint i0border, j0border, k0border, i1border, j1border, k1border;
  1501.    GLfloat u, v, w;
  1502.  
  1503.    u = s * width;
  1504.    if (tObj->WrapS==GL_REPEAT) {
  1505.       i0 = ((GLint) floor(u - 0.5F)) % width;
  1506.       i1 = (i0 + 1) & (width-1);
  1507.       i0border = i1border = 0;
  1508.    }
  1509.    else if (tObj->WrapS==GL_CLAMP_TO_EDGE) {
  1510.       GLfloat min = 1.0F / (2.0F * width);
  1511.       GLfloat max = 1.0F - min;
  1512.       if (s < min)
  1513.          i0 = 0;
  1514.       else if (s > max)
  1515.          i0 = width-1;
  1516.       else
  1517.          i0 = (GLint) (s * width);
  1518.       i1 = i0 + 1;
  1519.       if (i1 >= width)
  1520.          i1 = width - 1;
  1521.       i0border = i1border = 0;
  1522.    }
  1523.    else {
  1524.       ASSERT(tObj->WrapS==GL_CLAMP);
  1525.       if (u < 0.0F)  u = 0.0F;
  1526.       else if (u > width)  u = width;
  1527.       i0 = (GLint) floor(u - 0.5F);
  1528.       i1 = i0 + 1;
  1529.       i0border = (i0<0) | (i0>=width);
  1530.       i1border = (i1<0) | (i1>=width);
  1531.    }
  1532.  
  1533.    v = t * height;
  1534.    if (tObj->WrapT==GL_REPEAT) {
  1535.       j0 = ((GLint) floor(v - 0.5F)) % height;
  1536.       j1 = (j0 + 1) & (height-1);
  1537.       j0border = j1border = 0;
  1538.    }
  1539.    else if (tObj->WrapT==GL_CLAMP_TO_EDGE) {
  1540.       GLfloat min = 1.0F / (2.0F * height);
  1541.       GLfloat max = 1.0F - min;
  1542.       if (t < min)
  1543.          j0 = 0;
  1544.       else if (t > max)
  1545.          j0 = height-1;
  1546.       else
  1547.          j0 = (GLint) (t * height);
  1548.       j1 = j0 + 1;
  1549.       if (j1 >= height)
  1550.          j1 = height - 1;
  1551.       j0border = j1border = 0;
  1552.    }
  1553.    else {
  1554.       ASSERT(tObj->WrapT==GL_CLAMP);
  1555.       if (v < 0.0F)  v = 0.0F;
  1556.       else if (v > height)  v = height;
  1557.       j0 = (GLint) floor(v - 0.5F);
  1558.       j1 = j0 + 1;
  1559.       j0border = (j0<0) | (j0>=height);
  1560.       j1border = (j1<0) | (j1>=height);
  1561.    }
  1562.  
  1563.    w = r * depth;
  1564.    if (tObj->WrapR==GL_REPEAT) {
  1565.       k0 = ((GLint) floor(w - 0.5F)) % depth;
  1566.       k1 = (k0 + 1) & (depth-1);
  1567.       k0border = k1border = 0;
  1568.    }
  1569.    else if (tObj->WrapR==GL_CLAMP_TO_EDGE) {
  1570.       GLfloat min = 1.0F / (2.0F * depth);
  1571.       GLfloat max = 1.0F - min;
  1572.       if (r < min)
  1573.          k0 = 0;
  1574.       else if (r > max)
  1575.          k0 = depth-1;
  1576.       else
  1577.          k0 = (GLint) (r * depth);
  1578.       k1 = k0 + 1;
  1579.       if (k1 >= depth)
  1580.          k1 = depth - 1;
  1581.       k0border = k1border = 0;
  1582.    }
  1583.    else {
  1584.       ASSERT(tObj->WrapR==GL_CLAMP);
  1585.       if (r < 0.0F)  r = 0.0F;
  1586.       else if (r > depth)  r = depth;
  1587.       k0 = (GLint) floor(r - 0.5F);
  1588.       k1 = k0 + 1;
  1589.       k0border = (k0<0) | (k0>=depth);
  1590.       k1border = (k1<0) | (k1>=depth);
  1591.    }
  1592.  
  1593.    if (img->Border) {
  1594.       i0 += img->Border;
  1595.       i1 += img->Border;
  1596.       j0 += img->Border;
  1597.       j1 += img->Border;
  1598.       k0 += img->Border;
  1599.       k1 += img->Border;
  1600.       i0border = i1border = 0;
  1601.       j0border = j1border = 0;
  1602.       k0border = k1border = 0;
  1603.    }
  1604.    else {
  1605.       i0 &= (width-1);
  1606.       j0 &= (height-1);
  1607.       k0 &= (depth-1);
  1608.    }
  1609.  
  1610.    {
  1611.       GLfloat a = frac(u - 0.5F);
  1612.       GLfloat b = frac(v - 0.5F);
  1613.       GLfloat c = frac(w - 0.5F);
  1614.  
  1615.       GLint w000 = (GLint) ((1.0F-a)*(1.0F-b) * (1.0F-c) * 256.0F);
  1616.       GLint w010 = (GLint) (      a *(1.0F-b) * (1.0F-c) * 256.0F);
  1617.       GLint w001 = (GLint) ((1.0F-a)*      b  * (1.0F-c) * 256.0F);
  1618.       GLint w011 = (GLint) (      a *      b  * (1.0F-c) * 256.0F);
  1619.       GLint w100 = (GLint) ((1.0F-a)*(1.0F-b) * c * 256.0F);
  1620.       GLint w110 = (GLint) (      a *(1.0F-b) * c * 256.0F);
  1621.       GLint w101 = (GLint) ((1.0F-a)*      b  * c * 256.0F);
  1622.       GLint w111 = (GLint) (      a *      b  * c * 256.0F);
  1623.  
  1624.  
  1625.       GLubyte t000[4], t010[4], t001[4], t011[4];      /* texels */
  1626.       GLubyte t100[4], t110[4], t101[4], t111[4];
  1627.  
  1628.       if (k0border | i0border | j0border ) {
  1629.          t000[RCOMP] = tObj->BorderColor[0];
  1630.          t000[GCOMP] = tObj->BorderColor[1];
  1631.          t000[BCOMP] = tObj->BorderColor[2];
  1632.          t000[ACOMP] = tObj->BorderColor[3];
  1633.       }
  1634.       else {
  1635.          get_3d_texel( tObj, img, i0, j0, k0, t000 );
  1636.       }
  1637.       if (k0border | i1border | j0border) {
  1638.          t010[RCOMP] = tObj->BorderColor[0];
  1639.          t010[GCOMP] = tObj->BorderColor[1];
  1640.          t010[BCOMP] = tObj->BorderColor[2];
  1641.          t010[ACOMP] = tObj->BorderColor[3];
  1642.       }
  1643.       else {
  1644.          get_3d_texel( tObj, img, i1, j0, k0, t010 );
  1645.       }
  1646.       if (k0border | i0border | j1border) {
  1647.          t001[RCOMP] = tObj->BorderColor[0];
  1648.          t001[GCOMP] = tObj->BorderColor[1];
  1649.          t001[BCOMP] = tObj->BorderColor[2];
  1650.          t001[ACOMP] = tObj->BorderColor[3];
  1651.       }
  1652.       else {
  1653.          get_3d_texel( tObj, img, i0, j1, k0, t001 );
  1654.       }
  1655.       if (k0border | i1border | j1border) {
  1656.          t011[RCOMP] = tObj->BorderColor[0];
  1657.          t011[GCOMP] = tObj->BorderColor[1];
  1658.          t011[BCOMP] = tObj->BorderColor[2];
  1659.          t011[ACOMP] = tObj->BorderColor[3];
  1660.       }
  1661.       else {
  1662.          get_3d_texel( tObj, img, i1, j1, k0, t011 );
  1663.       }
  1664.  
  1665.       if (k1border | i0border | j0border ) {
  1666.          t100[RCOMP] = tObj->BorderColor[0];
  1667.          t100[GCOMP] = tObj->BorderColor[1];
  1668.          t100[BCOMP] = tObj->BorderColor[2];
  1669.          t100[ACOMP] = tObj->BorderColor[3];
  1670.       }
  1671.       else {
  1672.          get_3d_texel( tObj, img, i0, j0, k1, t100 );
  1673.       }
  1674.       if (k1border | i1border | j0border) {
  1675.          t110[RCOMP] = tObj->BorderColor[0];
  1676.          t110[GCOMP] = tObj->BorderColor[1];
  1677.          t110[BCOMP] = tObj->BorderColor[2];
  1678.          t110[ACOMP] = tObj->BorderColor[3];
  1679.       }
  1680.       else {
  1681.          get_3d_texel( tObj, img, i1, j0, k1, t110 );
  1682.       }
  1683.       if (k1border | i0border | j1border) {
  1684.          t101[RCOMP] = tObj->BorderColor[0];
  1685.          t101[GCOMP] = tObj->BorderColor[1];
  1686.          t101[BCOMP] = tObj->BorderColor[2];
  1687.          t101[ACOMP] = tObj->BorderColor[3];
  1688.       }
  1689.       else {
  1690.          get_3d_texel( tObj, img, i0, j1, k1, t101 );
  1691.       }
  1692.       if (k1border | i1border | j1border) {
  1693.          t111[RCOMP] = tObj->BorderColor[0];
  1694.          t111[GCOMP] = tObj->BorderColor[1];
  1695.          t111[BCOMP] = tObj->BorderColor[2];
  1696.          t111[ACOMP] = tObj->BorderColor[3];
  1697.       }
  1698.       else {
  1699.          get_3d_texel( tObj, img, i1, j1, k1, t111 );
  1700.       }
  1701.  
  1702.       /* MMX */
  1703.       rgba[0] = (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
  1704.                  w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0]  )
  1705.                 >> 8;
  1706.       rgba[1] = (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
  1707.                  w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
  1708.                 >> 8;
  1709.       rgba[2] = (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
  1710.                  w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
  1711.                 >> 8;
  1712.       rgba[3] = (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
  1713.                  w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
  1714.                 >> 8;
  1715.    }
  1716. }
  1717.  
  1718.  
  1719. static void
  1720. sample_3d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
  1721.                                   GLfloat s, GLfloat t, GLfloat r,
  1722.                                   GLfloat lambda, GLubyte rgba[4] )
  1723. {
  1724.    GLint level;
  1725.    if (lambda <= 0.5F)
  1726.       lambda = 0.0F;
  1727.    else if (lambda > tObj->M + 0.4999F)
  1728.       lambda = tObj->M + 0.4999F;
  1729.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  1730.    if (level > tObj->P)
  1731.       level = tObj->P;
  1732.  
  1733.    sample_3d_nearest( tObj, tObj->Image[level], s, t, r, rgba );
  1734. }
  1735.  
  1736.  
  1737. static void
  1738. sample_3d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
  1739.                                  GLfloat s, GLfloat t, GLfloat r,
  1740.                                  GLfloat lambda, GLubyte rgba[4] )
  1741. {
  1742.    GLint level;
  1743.    if (lambda <= 0.5F)
  1744.       lambda = 0.0F;
  1745.    else if (lambda > tObj->M + 0.4999F)
  1746.       lambda = tObj->M + 0.4999F;
  1747.    level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
  1748.    if (level > tObj->P)
  1749.       level = tObj->P;
  1750.  
  1751.    sample_3d_linear( tObj, tObj->Image[level], s, t, r, rgba );
  1752. }
  1753.  
  1754.  
  1755. static void
  1756. sample_3d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
  1757.                                  GLfloat s, GLfloat t, GLfloat r,
  1758.                                  GLfloat lambda, GLubyte rgba[4] )
  1759. {
  1760.    GLint level;
  1761.    if (lambda < 0.0F)
  1762.       lambda = 0.0F;
  1763.    else if (lambda > tObj->M)
  1764.       lambda = tObj->M;
  1765.    level = (GLint) (tObj->BaseLevel + lambda);
  1766.  
  1767.    if (level >= tObj->P) {
  1768.       sample_3d_nearest( tObj, tObj->Image[tObj->P], s, t, r, rgba );
  1769.    }
  1770.    else {
  1771.       GLubyte t0[4], t1[4];  /* texels */
  1772.       GLfloat f = frac(lambda);
  1773.       sample_3d_nearest( tObj, tObj->Image[level  ], s, t, r, t0 );
  1774.       sample_3d_nearest( tObj, tObj->Image[level+1], s, t, r, t1 );
  1775.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1776.       rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1777.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1778.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1779.    }
  1780. }
  1781.  
  1782.  
  1783. static void
  1784. sample_3d_linear_mipmap_linear( const struct gl_texture_object *tObj,
  1785.                                 GLfloat s, GLfloat t, GLfloat r,
  1786.                                 GLfloat lambda, GLubyte rgba[4] )
  1787. {
  1788.    GLint level;
  1789.    if (lambda < 0.0F)
  1790.       lambda = 0.0F;
  1791.    else if (lambda > tObj->M)
  1792.       lambda = tObj->M;
  1793.    level = (GLint) (tObj->BaseLevel + lambda);
  1794.  
  1795.    if (level >= tObj->P) {
  1796.       sample_3d_linear( tObj, tObj->Image[tObj->P], s, t, r, rgba );
  1797.    }
  1798.    else {
  1799.       GLubyte t0[4], t1[4];  /* texels */
  1800.       GLfloat f = frac(lambda);
  1801.       sample_3d_linear( tObj, tObj->Image[level  ], s, t, r, t0 );
  1802.       sample_3d_linear( tObj, tObj->Image[level+1], s, t, r, t1 );
  1803.       rgba[RCOMP] = (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1804.       rgba[GCOMP] = (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1805.       rgba[BCOMP] = (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1806.       rgba[ACOMP] = (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1807.    }
  1808. }
  1809.  
  1810.  
  1811. static void sample_nearest_3d( const struct gl_texture_object *tObj, GLuint n,
  1812.                                const GLfloat s[], const GLfloat t[],
  1813.                                const GLfloat u[], const GLfloat lambda[],
  1814.                                GLubyte rgba[][4] )
  1815. {
  1816.    GLuint i;
  1817.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1818.    (void) lambda;
  1819.    for (i=0;i<n;i++) {
  1820.       sample_3d_nearest( tObj, image, s[i], t[i], u[i], rgba[i] );
  1821.    }
  1822. }
  1823.  
  1824.  
  1825.  
  1826. static void sample_linear_3d( const struct gl_texture_object *tObj, GLuint n,
  1827.                               const GLfloat s[], const GLfloat t[],
  1828.                               const GLfloat u[], const GLfloat lambda[],
  1829.                               GLubyte rgba[][4] )
  1830. {
  1831.    GLuint i;
  1832.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1833.    (void) lambda;
  1834.    for (i=0;i<n;i++) {
  1835.       sample_3d_linear( tObj, image, s[i], t[i], u[i], rgba[i] );
  1836.    }
  1837. }
  1838.  
  1839.  
  1840. /*
  1841.  * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
  1842.  * return a texture sample.
  1843.  */
  1844. static void sample_lambda_3d( const struct gl_texture_object *tObj, GLuint n,
  1845.                               const GLfloat s[], const GLfloat t[],
  1846.                               const GLfloat u[], const GLfloat lambda[],
  1847.                               GLubyte rgba[][4] )
  1848. {
  1849.    GLuint i;
  1850.  
  1851.    for (i=0;i<n;i++) {
  1852.  
  1853.       if (lambda[i] > tObj->MinMagThresh) {
  1854.          /* minification */
  1855.          switch (tObj->MinFilter) {
  1856.             case GL_NEAREST:
  1857.                sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
  1858.                break;
  1859.             case GL_LINEAR:
  1860.                sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
  1861.                break;
  1862.             case GL_NEAREST_MIPMAP_NEAREST:
  1863.                sample_3d_nearest_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
  1864.                break;
  1865.             case GL_LINEAR_MIPMAP_NEAREST:
  1866.                sample_3d_linear_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
  1867.                break;
  1868.             case GL_NEAREST_MIPMAP_LINEAR:
  1869.                sample_3d_nearest_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
  1870.                break;
  1871.             case GL_LINEAR_MIPMAP_LINEAR:
  1872.                sample_3d_linear_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
  1873.                break;
  1874.             default:
  1875.                gl_problem(NULL, "Bad min filterin sample_3d_texture");
  1876.          }
  1877.       }
  1878.       else {
  1879.          /* magnification */
  1880.          switch (tObj->MagFilter) {
  1881.             case GL_NEAREST:
  1882.                sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
  1883.                break;
  1884.             case GL_LINEAR:
  1885.                sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
  1886.                break;
  1887.             default:
  1888.                gl_problem(NULL, "Bad mag filter in sample_3d_texture");
  1889.          }
  1890.       }
  1891.    }
  1892. }
  1893.  
  1894.  
  1895.  
  1896. /**********************************************************************/
  1897. /*                       Texture Sampling Setup                       */
  1898. /**********************************************************************/
  1899.  
  1900.  
  1901. /*
  1902.  * Setup the texture sampling function for this texture object.
  1903.  */
  1904. void gl_set_texture_sampler( struct gl_texture_object *t )
  1905. {
  1906.    if (!t->Complete) {
  1907.       t->SampleFunc = NULL;
  1908.    }
  1909.    else {
  1910.       GLboolean needLambda = (t->MinFilter != t->MagFilter);
  1911.  
  1912.       if (needLambda) {
  1913.          /* Compute min/mag filter threshold */
  1914.          if (t->MagFilter==GL_LINEAR
  1915.              && (t->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
  1916.                  t->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
  1917.             t->MinMagThresh = 0.5F;
  1918.          }
  1919.          else {
  1920.             t->MinMagThresh = 0.0F;
  1921.          }
  1922.       }
  1923.  
  1924.       switch (t->Dimensions) {
  1925.          case 1:
  1926.             if (needLambda) {
  1927.                t->SampleFunc = sample_lambda_1d;
  1928.             }
  1929.             else if (t->MinFilter==GL_LINEAR) {
  1930.                t->SampleFunc = sample_linear_1d;
  1931.             }
  1932.             else {
  1933.                ASSERT(t->MinFilter==GL_NEAREST);
  1934.                t->SampleFunc = sample_nearest_1d;
  1935.             }
  1936.             break;
  1937.          case 2:
  1938.             if (needLambda) {
  1939.                t->SampleFunc = sample_lambda_2d;
  1940.             }
  1941.             else if (t->MinFilter==GL_LINEAR) {
  1942.                t->SampleFunc = sample_linear_2d;
  1943.             }
  1944.             else {
  1945.                ASSERT(t->MinFilter==GL_NEAREST);
  1946.                if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
  1947.                    && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGB) {
  1948.                   t->SampleFunc = opt_sample_rgb_2d;
  1949.                }
  1950.                else if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
  1951.                    && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGBA) {
  1952.                   t->SampleFunc = opt_sample_rgba_2d;
  1953.                }
  1954.                else
  1955.                   t->SampleFunc = sample_nearest_2d;
  1956.             }
  1957.             break;
  1958.          case 3:
  1959.             if (needLambda) {
  1960.                t->SampleFunc = sample_lambda_3d;
  1961.             }
  1962.             else if (t->MinFilter==GL_LINEAR) {
  1963.                t->SampleFunc = sample_linear_3d;
  1964.             }
  1965.             else {
  1966.                ASSERT(t->MinFilter==GL_NEAREST);
  1967.                t->SampleFunc = sample_nearest_3d;
  1968.             }
  1969.             break;
  1970.          default:
  1971.             gl_problem(NULL, "invalid dimensions in gl_set_texture_sampler");
  1972.       }
  1973.    }
  1974. }
  1975.  
  1976.  
  1977.  
  1978. /**********************************************************************/
  1979. /*                      Texture Application                           */
  1980. /**********************************************************************/
  1981.  
  1982.  
  1983. /*
  1984.  * Combine incoming fragment color with texel color to produce output color.
  1985.  * Input:  textureSet - pointer to texture set/stage to apply
  1986.  *         format - base internal texture format
  1987.  *         n - number of fragments
  1988.  *         texels - array of texel colors
  1989.  * InOut:  rgba - incoming fragment colors modified by texel colors
  1990.  *                according to the texture environment mode.
  1991.  */
  1992. static void apply_texture( const GLcontext *ctx,
  1993.                            const struct gl_texture_set *texSet,
  1994.                            GLuint n,
  1995.                            GLubyte rgba[][4], CONST GLubyte texel[][4] )
  1996. {
  1997.    GLuint i;
  1998.    GLint Rc, Gc, Bc, Ac;
  1999.    GLenum format;
  2000.  
  2001.    ASSERT(texSet);
  2002.    ASSERT(texSet->Current);
  2003.    ASSERT(texSet->Current->Image[0]);
  2004.  
  2005.    format = texSet->Current->Image[0]->Format;
  2006.  
  2007. /*
  2008.  * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A
  2009.  * and B in [0,255]
  2010.  */
  2011. #define PROD(A,B)   (((GLint)(A) * ((GLint)(B)+1)) >> 8)
  2012.  
  2013.    if (format==GL_COLOR_INDEX) {
  2014.       format = GL_RGBA;  /* XXXX a hack! */
  2015.    }
  2016.  
  2017.    switch (texSet->EnvMode) {
  2018.       case GL_REPLACE:
  2019.      switch (format) {
  2020.         case GL_ALPHA:
  2021.            for (i=0;i<n;i++) {
  2022.           /* Cv = Cf */
  2023.                   /* Av = At */
  2024.                   rgba[i][ACOMP] = texel[i][ACOMP];
  2025.            }
  2026.            break;
  2027.         case GL_LUMINANCE:
  2028.            for (i=0;i<n;i++) {
  2029.           /* Cv = Lt */
  2030.                   GLint Lt = texel[i][RCOMP];
  2031.                   rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
  2032.                   /* Av = Af */
  2033.            }
  2034.            break;
  2035.         case GL_LUMINANCE_ALPHA:
  2036.            for (i=0;i<n;i++) {
  2037.                   GLint Lt = texel[i][RCOMP];
  2038.           /* Cv = Lt */
  2039.           rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
  2040.           /* Av = At */
  2041.           rgba[i][ACOMP] = texel[i][ACOMP];
  2042.            }
  2043.            break;
  2044.         case GL_INTENSITY:
  2045.            for (i=0;i<n;i++) {
  2046.           /* Cv = It */
  2047.                   GLint It = texel[i][RCOMP];
  2048.                   rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
  2049.                   /* Av = It */
  2050.                   rgba[i][ACOMP] = It;
  2051.            }
  2052.            break;
  2053.         case GL_RGB:
  2054.            for (i=0;i<n;i++) {
  2055.           /* Cv = Ct */
  2056.           rgba[i][RCOMP] = texel[i][RCOMP];
  2057.           rgba[i][GCOMP] = texel[i][GCOMP];
  2058.           rgba[i][BCOMP] = texel[i][BCOMP];
  2059.           /* Av = Af */
  2060.            }
  2061.            break;
  2062.         case GL_RGBA:
  2063.            for (i=0;i<n;i++) {
  2064.           /* Cv = Ct */
  2065.           rgba[i][RCOMP] = texel[i][RCOMP];
  2066.           rgba[i][GCOMP] = texel[i][GCOMP];
  2067.           rgba[i][BCOMP] = texel[i][BCOMP];
  2068.           /* Av = At */
  2069.           rgba[i][ACOMP] = texel[i][ACOMP];
  2070.            }
  2071.            break;
  2072.             default:
  2073.                gl_problem(ctx, "Bad format in apply_texture");
  2074.                return;
  2075.      }
  2076.      break;
  2077.  
  2078.       case GL_MODULATE:
  2079.          switch (format) {
  2080.         case GL_ALPHA:
  2081.            for (i=0;i<n;i++) {
  2082.           /* Cv = Cf */
  2083.           /* Av = AfAt */
  2084.           rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
  2085.            }
  2086.            break;
  2087.         case GL_LUMINANCE:
  2088.            for (i=0;i<n;i++) {
  2089.           /* Cv = LtCf */
  2090.                   GLint Lt = texel[i][RCOMP];
  2091.           rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
  2092.           rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
  2093.           rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
  2094.           /* Av = Af */
  2095.            }
  2096.            break;
  2097.         case GL_LUMINANCE_ALPHA:
  2098.            for (i=0;i<n;i++) {
  2099.           /* Cv = CfLt */
  2100.                   GLint Lt = texel[i][RCOMP];
  2101.           rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
  2102.           rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
  2103.           rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
  2104.           /* Av = AfAt */
  2105.           rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
  2106.            }
  2107.            break;
  2108.         case GL_INTENSITY:
  2109.            for (i=0;i<n;i++) {
  2110.           /* Cv = CfIt */
  2111.                   GLint It = texel[i][RCOMP];
  2112.           rgba[i][RCOMP] = PROD( rgba[i][RCOMP], It );
  2113.           rgba[i][GCOMP] = PROD( rgba[i][GCOMP], It );
  2114.           rgba[i][BCOMP] = PROD( rgba[i][BCOMP], It );
  2115.           /* Av = AfIt */
  2116.           rgba[i][ACOMP] = PROD( rgba[i][ACOMP], It );
  2117.            }
  2118.            break;
  2119.         case GL_RGB:
  2120.            for (i=0;i<n;i++) {
  2121.           /* Cv = CfCt */
  2122.           rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
  2123.           rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
  2124.           rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
  2125.           /* Av = Af */
  2126.            }
  2127.            break;
  2128.         case GL_RGBA:
  2129.            for (i=0;i<n;i++) {
  2130.           /* Cv = CfCt */
  2131.           rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
  2132.           rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
  2133.           rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
  2134.           /* Av = AfAt */
  2135.           rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
  2136.            }
  2137.            break;
  2138.             default:
  2139.                gl_problem(ctx, "Bad format (2) in apply_texture");
  2140.                return;
  2141.      }
  2142.      break;
  2143.  
  2144.       case GL_DECAL:
  2145.          switch (format) {
  2146.             case GL_ALPHA:
  2147.             case GL_LUMINANCE:
  2148.             case GL_LUMINANCE_ALPHA:
  2149.             case GL_INTENSITY:
  2150.                /* undefined */
  2151.                break;
  2152.         case GL_RGB:
  2153.            for (i=0;i<n;i++) {
  2154.           /* Cv = Ct */
  2155.           rgba[i][RCOMP] = texel[i][RCOMP];
  2156.           rgba[i][GCOMP] = texel[i][GCOMP];
  2157.           rgba[i][BCOMP] = texel[i][BCOMP];
  2158.           /* Av = Af */
  2159.            }
  2160.            break;
  2161.         case GL_RGBA:
  2162.            for (i=0;i<n;i++) {
  2163.           /* Cv = Cf(1-At) + CtAt */
  2164.           GLint t = texel[i][ACOMP], s = 255 - t;
  2165.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(texel[i][RCOMP],t);
  2166.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(texel[i][GCOMP],t);
  2167.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(texel[i][BCOMP],t);
  2168.           /* Av = Af */
  2169.            }
  2170.            break;
  2171.             default:
  2172.                gl_problem(ctx, "Bad format (3) in apply_texture");
  2173.                return;
  2174.      }
  2175.      break;
  2176.  
  2177.       case GL_BLEND:
  2178.          Rc = (GLint) (texSet->EnvColor[0] * 255.0F);
  2179.          Gc = (GLint) (texSet->EnvColor[1] * 255.0F);
  2180.          Bc = (GLint) (texSet->EnvColor[2] * 255.0F);
  2181.          Ac = (GLint) (texSet->EnvColor[3] * 255.0F);
  2182.      switch (format) {
  2183.         case GL_ALPHA:
  2184.            for (i=0;i<n;i++) {
  2185.           /* Cv = Cf */
  2186.           /* Av = AfAt */
  2187.                   rgba[i][ACOMP] = PROD(rgba[i][ACOMP], texel[i][ACOMP]);
  2188.            }
  2189.            break;
  2190.             case GL_LUMINANCE:
  2191.            for (i=0;i<n;i++) {
  2192.           /* Cv = Cf(1-Lt) + CcLt */
  2193.           GLint Lt = texel[i][RCOMP], s = 255 - Lt;
  2194.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
  2195.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
  2196.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
  2197.           /* Av = Af */
  2198.            }
  2199.            break;
  2200.         case GL_LUMINANCE_ALPHA:
  2201.            for (i=0;i<n;i++) {
  2202.           /* Cv = Cf(1-Lt) + CcLt */
  2203.           GLint Lt = texel[i][RCOMP], s = 255 - Lt;
  2204.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
  2205.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
  2206.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
  2207.           /* Av = AfAt */
  2208.           rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
  2209.            }
  2210.            break;
  2211.             case GL_INTENSITY:
  2212.            for (i=0;i<n;i++) {
  2213.           /* Cv = Cf(1-It) + CcLt */
  2214.           GLint It = texel[i][RCOMP], s = 255 - It;
  2215.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, It);
  2216.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, It);
  2217.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, It);
  2218.                   /* Av = Af(1-It) + Ac*It */
  2219.                   rgba[i][ACOMP] = PROD(rgba[i][ACOMP], s) + PROD(Ac, It);
  2220.                }
  2221.                break;
  2222.         case GL_RGB:
  2223.            for (i=0;i<n;i++) {
  2224.           /* Cv = Cf(1-Ct) + CcCt */
  2225.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
  2226.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
  2227.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
  2228.           /* Av = Af */
  2229.            }
  2230.            break;
  2231.         case GL_RGBA:
  2232.            for (i=0;i<n;i++) {
  2233.           /* Cv = Cf(1-Ct) + CcCt */
  2234.           rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
  2235.           rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
  2236.           rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
  2237.           /* Av = AfAt */
  2238.           rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
  2239.            }
  2240.            break;
  2241.             default:
  2242.                gl_problem(ctx, "Bad format (4) in apply_texture");
  2243.                return;
  2244.      }
  2245.      break;
  2246.  
  2247.       default:
  2248.          gl_problem(ctx, "Bad env mode in apply_texture");
  2249.          return;
  2250.    }
  2251. #undef PROD
  2252. }
  2253.  
  2254.  
  2255.  
  2256. /*
  2257.  * Apply a stage/set of texture mapping to the incoming fragments.
  2258.  */
  2259. void gl_texture_pixels( GLcontext *ctx, GLuint texSet, GLuint n,
  2260.                         const GLfloat s[], const GLfloat t[],
  2261.                         const GLfloat r[], GLfloat lambda[],
  2262.                         GLubyte rgba[][4] )
  2263. {
  2264.    GLuint mask = (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D) << (texSet * 4);
  2265.    if (ctx->Texture.Enabled & mask) {
  2266.       const struct gl_texture_set *textureSet = &ctx->Texture.Set[texSet];
  2267.       if (textureSet->Current && textureSet->Current->SampleFunc) {
  2268.  
  2269.          GLubyte texel[PB_SIZE][4];
  2270.  
  2271.          if (textureSet->Current->MinLod != -1000.0
  2272.              || textureSet->Current->MaxLod != 1000.0) {
  2273.             /* apply LOD clamping to lambda */
  2274.             GLfloat min = textureSet->Current->MinLod;
  2275.             GLfloat max = textureSet->Current->MaxLod;
  2276.             GLuint i;
  2277.             for (i=0;i<n;i++) {
  2278.                GLfloat l = lambda[i];
  2279.                lambda[i] = CLAMP(l, min, max);
  2280.             }
  2281.          }
  2282.  
  2283.          /* Sample the texture. */
  2284.          (*textureSet->Current->SampleFunc)( textureSet->Current, n,
  2285.                                              s, t, r, lambda, texel );
  2286.  
  2287.          apply_texture( ctx, textureSet, n, rgba, texel );
  2288.       }
  2289.    }
  2290. }
  2291.